#include "randomGeneratorTest.h"
#include <algorithm>
using namespace std;

#define abs(x) ((x) < 0 ? - (x) : (x))

RandomGeneratorTest::RandomGeneratorTest()
{
}
 
void RandomGeneratorTest::setUp()
{
}

void RandomGeneratorTest::tearDown()
{
}

void RandomGeneratorTest::testGenerator()
{
	vector<int> v;
	int nb = 10000;
	float t0 = 40;
	float t1 = 30;
	float t2 = 20;
	float t3 = 10;
	float epsilon = 1.0;
	
	unsigned int repetitions = 100;
	float sumErr0=0, sumErr1=0, sumErr2=0, sumErr3=0;
	float moyErr0=0, moyErr1=0, moyErr2=0, moyErr3=0;
	
	for (unsigned int i=0; i < repetitions; i++)
	{
		// genere le vecteur
		v.clear();
		v = generateList(nb, t0, t1, t2, t3);
		
		// compte le nb de chaque
		int nb0=0, nb1=0, nb2=0, nb3=0;
		for_each(v.begin(), v.end(), 
			[&nb0, &nb1,&nb2, &nb3](int i)
			{
				switch(i)
				{
					case 0 : nb0++; break;
					case 1 : nb1++; break; 
					case 2 : nb2++; break;
					case 3 : nb3++; break;
				}
			}
		);
		
		// calcule le % de chaque
		float rate0=0, rate1=0, rate2=0, rate3=0; 
		rate0 = nb0/(nb*1.0)*100;
		rate1 = nb1/(nb*1.0)*100;
		rate2 = nb2/(nb*1.0)*100;
		rate3 = nb3/(nb*1.0)*100;
		
		// maj cumul erreur
		sumErr0 += abs(t0-rate0);
		sumErr1 += abs(t1-rate1);
		sumErr2 += abs(t2-rate2);
		sumErr3 += abs(t3-rate3);
	}
	
	// calcul erreur moyenne
	moyErr0 = sumErr0 / (repetitions*1.0);
	moyErr1 = sumErr1 / (repetitions*1.0);
	moyErr2 = sumErr2 / (repetitions*1.0);
	moyErr3 = sumErr3 / (repetitions*1.0);

	// verif erreur moyenne par rapport au seuil de tolerance epsilon
	CPPUNIT_ASSERT( moyErr0 < epsilon );
	CPPUNIT_ASSERT( moyErr1 < epsilon );
	CPPUNIT_ASSERT( moyErr2 < epsilon );
	CPPUNIT_ASSERT( moyErr3 < epsilon );
	
}

void RandomGeneratorTest::testListCreator()
{
	size_t size = 1000;
	unsigned int trimming = 24;
	float t0 = 40;
	float t1 = 30;
	float t2 = 20;
	float t3 = 10;
	float epsilon = 1.0;
	int nb0=0, nb1=0, nb2=0, nb3=0;
	DnaSeq * list = createList(size, trimming, t0, t1, t2, t3);
	
	// conversion liste complète vers string	
	string s="";
	for (unsigned int i=0; i<size; ++i)
	{
		s = conv2string(list[i],s);
	}
	
	// decompte des lettres
	for (unsigned int i=0; i<s.length(); i++)
	{
		switch(s[i])
		{
			case 'A' : nb0++; break;
			case 'C' : nb1++; break;
			case 'G' : nb2++; break;
			case 'T' : nb3++; break;	
		}
	}
	
	// verif erreur moyenne par rapport au seuil de tolerance epsilon
	CPPUNIT_ASSERT( abs((nb0 / (size*trimming*1.0)*100) - t0) < epsilon);
	CPPUNIT_ASSERT( abs((nb1 / (size*trimming*1.0)*100) - t1) < epsilon);
	CPPUNIT_ASSERT( abs((nb2 / (size*trimming*1.0)*100) - t2) < epsilon);
	CPPUNIT_ASSERT( abs((nb3 / (size*trimming*1.0)*100) - t3) < epsilon);	
}

void RandomGeneratorTest::testCount()
{
	size_t size = 1000;
	unsigned int trimming = 24;
	float t0 = 0.4;
	float t1 = 0.3;
	float t2 = 0.2;
	float t3 = 0.1;
	DnaSeq * list = createList(size, trimming, t0, t1, t2, t3);
	map<int, int> map;
	
	map = count(size, list);

	// calcul des taux effectifs
	float tt0 = map[0] * 1.0 / (size * trimming);
	float tt1 = map[1] * 1.0 / (size * trimming);
	float tt2 = map[2] * 1.0 / (size * trimming);
	float tt3 = map[3] * 1.0 / (size * trimming);	
	
	// test avec un seuil de tolerance de 1				
	float epsilon = 1;	
	CPPUNIT_ASSERT( abs(tt0 - t0) < epsilon);
	CPPUNIT_ASSERT( abs(tt1 - t1) < epsilon);
	CPPUNIT_ASSERT( abs(tt2 - t2) < epsilon);
	CPPUNIT_ASSERT( abs(tt3 - t3) < epsilon);

}
